/*稀疏数组是指 索引不连续，
数组长度大于元素个数的数组，通俗地说就是 有空隙的数组。
稀疏数组的缺失元素时会返回 undefined，空隙值在控制台输出是empty。

javaScript中的数组并不像我们在C或java等语言中遇到的常规数组，在js中数组并不是起始地址+长度构成的一片连续的地址空间。
javascript中数组其实就是个对象,只不过会自动管理一些"数字"属性和length属性罢了。

****特别注意：可见JavaScript中的数组根本没有索引,因为索引应该是数字,而JavaScript中数组的索引其实是字符串。

这些表现的根本原因就是：JavaScript中的对象就是字符串到任意值的键值对。

稀疏数组特性:
    访问速度慢
    内存利用率高

    稀疏数组使用的是字典模式，也称为 散列表模式，
    该模式下 V8 使用散列表来存储对象属性。
    由于每次访问时都需要计算哈希值（实际上只需要计算一次，哈希值会被缓存）和寻址，
    所以访问速度非常慢。另一方面，对比起使用一段连续的内存空间来存储稀疏数组，散列表的方式会大幅度地节省内存空间。

密集数组特性：
    密集数组在内存空间中是被存储在一个连续的类数组里，
    引擎可以直接通过数组索引访问到数组元素，所以速度会非常快。

 */


//以下方式生成稀疏数组
//构造函数声明一个没有元素的数组
var arr1 = new Array(5);

console.log('arr1: ',arr1) // [ <5 empty items> ]


//指定的索引值大于数组长度
var arr2 = []
arr2[5] = 0
console.log('arr2: ',arr2) // [ <5 empty items>, 0 ]

//指定大于元素个数的数组长度
var arr3 = []
arr3.length = 5
console.log('arr3: ',arr3) // [ <5 empty items> ]

// 数组直接量中省略值
var arr4 = [0,,,,,]
console.log('arr4: ',arr4); // [ 0, <4 empty items> ]

//删除数组元素
var arr5 = [1,2,3,4,5]
delete arr5[4]
console.log('arr5: ',arr5); // [ 1, 2, 3, 4, <1 empty item> ]


//稀疏数组中那个空隙元素值empty是  undefined
// 但 empty 和 undefined 不是一个含义，arr6是一个密集数组
var arr6 = [undefined,undefined]
console.log('arr6: ',arr6); // [ undefined, undefined ]

/*
稀疏数组的缺失元素时会返回 undefined，
是因为 JS 引擎在发现元素缺失时会临时赋值 undefined，类似于 JS 变量的声明提升
 */


//稀疏数组转化为密集数组
var arr7 = new Array(5)
//ES5的方式
var arr8 =Array.apply(null,arr7)
//ES6的方式
var arr9 = Array.from(arr7)
console.log('arr7-->arr8: ',arr8) //[ undefined, undefined, undefined, undefined, undefined ]
console.log('arr7-->arr9: ',arr9) //[ undefined, undefined, undefined, undefined, undefined ]



//特别注意： JavaScript中的数组根本没有索引,因为索引应该是数字,而JavaScript中数组的索引其实是字符串。
var arr10 = [1,2,3]
console.log('arr10:',arr10[1]); // 2
console.log('arr10:',arr10['1']); // 2


//以下是稀疏数组的特殊表现

//for-in 语句 语句只会遍历对象的可枚举属性，不会遍历稀疏数组中的缺失元素。
var forIn = [1,,,,5];
for (var i in forIn) { console.log('forIn:',forIn[i]) };    // 1 5
for (var i of forIn) { console.log('forIn i',i) };       // 1 undefined undefined undefined 5


//JSON.string()方法会将缺失的元素填充为null
console.log("JSON.stringify:",JSON.stringify([1, , , 4]));   // "[1,null,null,4]"

//join 方法 缺失元素占的坑还是会被保留。
var join = new Array(5);
console.log("join:",join.join());   // ",,,,"

//sort 方法 不会遍历缺失元素，数组能正常排序，同时会返回与源数组相同的长度。
var sort = [5,,,,1];
console.log("sort: ",sort.sort());    // [1, 5, empty × 3]

//map 方法 不会遍历缺失元素，但返回的结果具有与源数组相同的长度和空隙。
var map = [1,,,,5];
console.log('map:',map.map(i => i));       // [1, empty × 3, 5]
console.log('filter:',map.filter(i => i));       // [1, empty × 3, 5]
